package com.qiguliuxing.dts.merchant.service;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SimplePropertyPreFilter;
import com.github.pagehelper.PageInfo;
import com.qiguliuxing.dts.common.util.DateTimeUtils;
import com.qiguliuxing.dts.common.util.ResponseUtils;
import com.qiguliuxing.dts.db.domain.DtsMerchantAccount;
import com.qiguliuxing.dts.db.domain.DtsMerchantAccountTrace;
import com.qiguliuxing.dts.db.domain.DtsMerchantDailyStatis;
import com.qiguliuxing.dts.db.domain.DtsMerchantWithdrawalAccount;
import com.qiguliuxing.dts.merchant.support.MerchantResponseCode;
import com.qiguliuxing.dts.merchant.support.MerchantResponseUtils;
import com.qiguliuxing.dts.service.merchant.BillStatisService;
import com.qiguliuxing.dts.service.merchant.WithdrawAccountService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 财务账单服务类
 *
 * @author qiguliuxing
 * @since 1.0.0
 */
@Service
public class MerchantBillService {
    private static final Logger logger = LoggerFactory.getLogger(MerchantBillService.class);

    @Autowired
    private BillStatisService billStatisService;

    @Autowired
    private WithdrawAccountService withdrawAccountService;

    public Object listBill(Integer page, Integer limit, String sort, String order, Integer brandId, List<String> dateRange) {
        List<DtsMerchantDailyStatis> merchantDailyStatisList = billStatisService.querySelective(brandId, page, limit, sort, order, dateRange);
        long total = PageInfo.of(merchantDailyStatisList).getTotal();
        Map<String, Object> data = new HashMap<>();
        data.put("total", total);
        data.put("items", merchantDailyStatisList);
        return ResponseUtils.ok(data);
    }

    public Object overview(Integer brandId) {
        if (brandId == null) {
            logger.error("账号总览查询出错，传入的当前商户为空！");
            return ResponseUtils.serious();
        }
        // 当前账号（已统计的数据）
        DtsMerchantAccount dtsMerchantAccount = billStatisService.getAccountByBrandId(brandId);

        /**
         * 未统计的营业数据
         * 只考虑当天未统计，忽略第二天统计账单job未执行之前的查询，这里存在一段时间上一个交易日尚未统计的空隙时间
         * todo 后续需优化 当日账单job未执行，即上一个交易日尚未统计造成的部分账号总金额修补的问题
         *  可验证最后统计日期之后，该商户是否有未统计的账单数据，存在则补充缺失的统计，job则需要判断交易是否已经统计
         */
        String currday = DateTimeUtils.getDateDisplayString(LocalDateTime.now());
        DtsMerchantDailyStatis dtsMerchantDailyStatis = billStatisService.merchantDailyStatis(brandId, currday);

        BigDecimal remainAmount = dtsMerchantAccount == null ? new BigDecimal(0) : dtsMerchantAccount.getRemainAmount();
        BigDecimal currAmount = dtsMerchantDailyStatis == null ? new BigDecimal(0) : dtsMerchantDailyStatis.getActualAmount();
        Integer orderCnt = dtsMerchantDailyStatis == null ? 0 : dtsMerchantDailyStatis.getOrderCnt();
        Integer refundCnt = dtsMerchantDailyStatis == null ? 0 : dtsMerchantDailyStatis.getRefundCnt();

        // 账号总金额（剩余+当天收入）
        BigDecimal totalAmount = remainAmount.add(currAmount);

        BigDecimal applyWithdrawAmount = billStatisService.getApplyWithdrawAmount(brandId);
        // 可提现金额 = 账号总金额（剩余+当天收入）- 今日总收入 - 已申请提现中金额
        BigDecimal withdrawableAmount = totalAmount.subtract(currAmount).subtract(applyWithdrawAmount);

        Map<String, Object> data = new HashMap<>();
        data.put("totalAmount", totalAmount);
        data.put("withdrawableAmount", withdrawableAmount);
        data.put("currAmount", currAmount);
        data.put("orderCnt", orderCnt);
        data.put("refundCnt", refundCnt);
        return ResponseUtils.ok(data);
    }

    /**
     * 商户提现申请
     *
     * @param brandId
     * @param withdrawType
     * @param amt
     * @return
     */
    public Object apply(Integer brandId, Integer withdrawType, String amt) {
        BigDecimal withdrawAmount = new BigDecimal(amt);
        if (!billStatisService.withdrawAmountBeyondCheck(brandId, withdrawAmount)) {
            logger.error("商户提现申请错误:{}", MerchantResponseCode.WITHDRAW_AMOUNT_BEYOND.desc());
            return MerchantResponseUtils.fail(MerchantResponseCode.WITHDRAW_AMOUNT_BEYOND);
        }

        DtsMerchantWithdrawalAccount withdrawAccount = withdrawAccountService.getWithdrawAccount(brandId, withdrawType);
        // 未传入支付类型, 表示默认提现账号不存在
        if (withdrawAccount == null) {
            if (withdrawType == null) {
                logger.error("商户提现申请错误:{}", MerchantResponseCode.WITHDRAW_NO_DEFAULT_ACCOUNT.desc());
                return MerchantResponseUtils.fail(MerchantResponseCode.WITHDRAW_NO_DEFAULT_ACCOUNT);
            } else {
                logger.error("商户提现申请错误:{}", MerchantResponseCode.WITHDRAW_ACCOUNT_NO_CONFIG.desc());
                return MerchantResponseUtils.fail(MerchantResponseCode.WITHDRAW_ACCOUNT_NO_CONFIG);
            }
        }


        billStatisService.apply(brandId, withdrawAccount, withdrawAmount);
        return ResponseUtils.ok();
    }

    /**
     * 商户提现的分页查询
     *
     * @param page
     * @param limit
     * @param sort
     * @param order
     * @param brandId
     * @return
     */
    public Object listWithdraw(Integer page, Integer limit, String sort, String order, Integer brandId, String accountNo, List<Byte> statusArray, List<LocalDateTime> time) {
        List<DtsMerchantAccountTrace> dtsMerchantAccountTraceList = withdrawAccountService.querySelective(brandId, page, limit, sort, order, accountNo, statusArray, time);
        long total = PageInfo.of(dtsMerchantAccountTraceList).getTotal();
        Map<String, Object> data = new HashMap<>();
        data.put("total", total);
        data.put("items", dtsMerchantAccountTraceList);
        return ResponseUtils.ok(data);
    }
}
